package com.jet.merchant.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jet.merchant.domain.entity.*;
import com.jet.merchant.service.*;
import com.jet.core.model.vo.PageVo;
import com.jet.core.enums.CommonDeleted;
import com.jet.core.enums.CommonStatus;
import com.jet.core.enums.IEnum;
import com.jet.core.exception.CustomException;
import com.jet.merchant.domain.dto.MerchantStoreDto;
import com.jet.merchant.domain.enums.BasicConfigConst;
import com.jet.merchant.domain.query.MerchantStoreQuery;
import com.jet.merchant.domain.vo.MerchantStoreVo;
import com.jet.merchant.domain.vo.RegionPathVo;
import com.jet.merchant.mapper.MerchantStoreMapper;
import com.jet.core.utils.IdUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author author
 * @since 2025-02-14
 */
@Service
public class MerchantStoreServiceImpl extends ServiceImpl<MerchantStoreMapper, MerchantStore> implements IMerchantStoreService {

    private final IMerchantStoreBindQuotaService merchantStoreBindQuotaService;
    private final IMerchantRegionService merchantRegionService;
    private final IClerkAccountRoleMapService clerkAccountRoleMapService;
    private final IClerkAccountService clerkAccountService;
    private final IClerkRoleService clerkRoleService;

    public MerchantStoreServiceImpl(IMerchantStoreBindQuotaService merchantStoreBindQuotaService, IMerchantRegionService merchantRegionService, IClerkAccountRoleMapService clerkAccountRoleMapService, IClerkAccountService clerkAccountService, IClerkRoleService clerkRoleService) {
        this.merchantStoreBindQuotaService = merchantStoreBindQuotaService;
        this.merchantRegionService = merchantRegionService;
        this.clerkAccountRoleMapService = clerkAccountRoleMapService;
        this.clerkAccountService = clerkAccountService;
        this.clerkRoleService = clerkRoleService;
    }

    @Override
    public void register(long merchantNo, long storeNo, String accountId, String phone) {
        MerchantStore entity = new MerchantStore();
        entity.setId(IdUtil.generateLower());
        entity.setStoreNo(storeNo);
        entity.setMerchantNo(merchantNo);
        entity.setStoreName("智慧门店");
        entity.setStorePhone(phone);
        entity.setAccountId(accountId);
        entity.setMain(true);
        save(entity);
        super.save(entity);
//        asyncGoods(merchantNo, storeNo);
    }

    @Override
    @Transactional(rollbackFor = CustomException.class)
    public void create(long merchantNo, MerchantStoreDto dto) {
        long storeNo = generateNextStoreNo(merchantNo);
        clerkAccountService.editStoreNo(dto.getAccountId(), storeNo, dto.getRoleId());

        LocalDate now = LocalDate.now();
        MerchantStore entity = new MerchantStore();
        BeanUtils.copyProperties(dto, entity);
        entity.setId(IdUtil.generateLower());
        entity.setMerchantNo(merchantNo);
        entity.setStoreNo(storeNo);
        entity.setEndDate(now.plusDays(15));
        super.save(entity);
        asyncGoods(merchantNo, storeNo);
    }

    private long generateNextStoreNo(long merchantNo) {
        long storeCount = countByMerchantNo(merchantNo);
        return BasicConfigConst.STORE_START_NO + storeCount + 1;
    }

    /**
     * 同步商品信息到门店
     *
     * @param merchantNo
     * @param storeNo
     */
    @Override
    public void asyncGoods(long merchantNo, long storeNo) {
        // TODO 调用feign同步
//        SpuQuery spuQuery = new SpuQuery();
//        List<SpuListVo> spus = spuService.list(merchantNo, spuQuery);
//        spus.forEach(spu -> {
//            StockSpuDto spuDto = new StockSpuDto();
//            BeanUtils.copyProperties(spu, spuDto);
//            spuDto.setSpuId(spu.getId());
//            spuDto.setPictures(JSONUtil.toJsonStr(spu.getPictures()));
//            List<SkuVo> skus = skuService.findAllBySpuId(spu.getId());
//            List<StockSkuDto> stockSkus = skus.stream().map(sku -> {
//                StockSkuDto skuDto = new StockSkuDto();
//                BeanUtils.copyProperties(sku, skuDto);
//                skuDto.setSkuId(sku.getId());
//                skuDto.setPurchaseAmount(AmountUtil.parse(sku.getPurchaseAmount()));
//                skuDto.setReferenceAmount(AmountUtil.parse(sku.getReferenceAmount()));
//                skuDto.setSkuWeight(StockUtil.parse(sku.getSkuWeight()));
//                return skuDto;
//            }).collect(Collectors.toList());
//            spuDto.setSkus(stockSkus);
//            stockSpuService.batchEdit(merchantNo, storeNo, spuDto);
//        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void edit(String id, MerchantStoreDto dto) {
        MerchantStore store = super.getById(id);
        if (store == null) {
            return;
        }
        clerkAccountService.editStoreNo(dto.getAccountId(), store.getStoreNo(), dto.getRoleId());

        MerchantStore entity = new MerchantStore();
        BeanUtils.copyProperties(dto, entity);
        entity.setId(id);
        entity.setUpdateTime(LocalDateTime.now());
        super.updateById(entity);
    }

    @Override
    public void editName(long merchantNo, long storeNo, String name) {
        Wrapper<MerchantStore> wrapper = new LambdaQueryWrapper<MerchantStore>()
                .eq(MerchantStore::getMerchantNo, merchantNo)
                .eq(MerchantStore::getStoreNo, storeNo);
        MerchantStore store = super.getOne(wrapper);
        if (store == null) {
            throw new CustomException("门店信息错误");
        }
        store.setStoreName(name);
        super.updateById(store);
    }

    @Override
    public void editStatus(String id, int status) {
        if (IEnum.getByCode(status, CommonStatus.class) == null) {
            throw new CustomException("状态信息错误");
        }
        MerchantStore store = new MerchantStore();
        store.setId(id);
        store.setStatus(status);
        super.updateById(store);
    }

    @Override
    @Transactional(rollbackFor = CustomException.class)
    public void bindQuota(long merchantNo, long addMonth, long bindStoreNo) {
        Wrapper<MerchantStore> wrapper = new LambdaQueryWrapper<MerchantStore>()
                .eq(MerchantStore::getMerchantNo, merchantNo)
                .eq(MerchantStore::getStoreNo, bindStoreNo);
        MerchantStore store = super.getOne(wrapper);
        if (store == null) {
            throw new CustomException("门店信息错误");
        }
        LocalDate now = LocalDate.now();
        if (store.getEndDate() != null) {
            if (store.getEndDate().isAfter(now)) {
                now = store.getEndDate();
            }
        }
        LocalDate endDate = now.plusMonths(addMonth);
        store.setEndDate(endDate);
        super.updateById(store);
        long addDays = Period.between(now, endDate).getDays();

        MerchantStoreBindQuota log = new MerchantStoreBindQuota();
        log.setId(IdUtil.generateLower());
        log.setMerchantNo(merchantNo);
        log.setStoreNo(bindStoreNo);
        log.setBeforeEndDate(store.getEndDate());
        log.setAddDays(addDays);
        log.setAfterEndDate(endDate);
        log.setCreateTime(LocalDateTime.now());
        merchantStoreBindQuotaService.save(log);
    }

    @Override
    public void delete(String id) {
        MerchantStore entity = super.getById(id);
        if (entity == null) {
            return;
        }
        if (entity.getMain()) {
            throw new CustomException("主门店不允许直接删除");
        }
        entity.setDeleted(CommonDeleted.DELETED.getCode());
        super.updateById(entity);
    }

    @Override
    public MerchantStoreVo findById(String id) {
        MerchantStore entity = super.getById(id);
        if (entity == null) {
            return null;
        }
        return convertStore(entity);
    }

    @Override
    public MerchantStore findMain(long merchantNo) {
        Wrapper<MerchantStore> wrapper = new LambdaQueryWrapper<MerchantStore>()
                .eq(MerchantStore::getMerchantNo, merchantNo)
                .eq(MerchantStore::getMain, true);
        return super.getOne(wrapper);
    }

    @Override
    public MerchantStoreVo findByStoreNo(long merchantNo, long storeNo) {
        Wrapper<MerchantStore> wrapper = new LambdaQueryWrapper<MerchantStore>()
                .eq(MerchantStore::getMerchantNo, merchantNo)
                .eq(MerchantStore::getStoreNo, storeNo);
        MerchantStore entity = super.getOne(wrapper);
        if (entity == null) {
            return null;
        }
        return convertStore(entity);
    }

    @Override
    public List<MerchantStoreVo> findAllByStoreNos(long merchantNo, List<Long> storeNos) {
        Wrapper<MerchantStore> wrapper = new LambdaQueryWrapper<MerchantStore>()
                .eq(MerchantStore::getMerchantNo, merchantNo)
                .in(CollUtil.isNotEmpty(storeNos), MerchantStore::getStoreNo, storeNos);
        List<MerchantStore> stores = super.list(wrapper);
        return stores.stream().map(this::convertStore).collect(Collectors.toList());
    }

    @Override
    public List<MerchantStore> findAllByMerchantNo(long merchantNo) {
        Wrapper<MerchantStore> wrapper = new LambdaQueryWrapper<MerchantStore>()
                .eq(MerchantStore::getMerchantNo, merchantNo);
        return super.list(wrapper);
    }

    @Override
    public long countByMerchantNo(long merchantNo) {
        Wrapper<MerchantStore> wrapper = new LambdaQueryWrapper<MerchantStore>()
                .eq(MerchantStore::getMerchantNo, merchantNo);
        return super.count(wrapper);
    }

    @Override
    public PageVo<MerchantStoreVo> page(long merchantNo, MerchantStoreQuery query) {
        Page<MerchantStore> tempQuery = new Page<>(query.getPageIndex(), query.getPageSize());

        Wrapper<MerchantStore> wrapper = new LambdaQueryWrapper<MerchantStore>()
                .eq(MerchantStore::getDeleted, CommonDeleted.NOT_DELETED.getCode())
                .eq(MerchantStore::getMerchantNo, merchantNo)
                .and(StrUtil.isNotBlank(query.getSearchKey()), i -> i
                        .like(MerchantStore::getStoreName, query.getSearchKey())
                        .or()
                        .like(MerchantStore::getStorePhone, query.getSearchKey())
                )
                .orderByAsc(MerchantStore::getStoreNo);
        IPage<MerchantStore> page = super.page(tempQuery, wrapper);

        List<MerchantStoreVo> vos = page.getRecords().stream().map(this::convertStore).collect(Collectors.toList());
        return PageVo.result(query.getPageIndex(), query.getPageSize(), (int) page.getTotal(), vos);
    }

    @Override
    public List<MerchantStoreVo> list(long merchantNo) {
        Wrapper<MerchantStore> wrapper = new LambdaQueryWrapper<MerchantStore>()
                .eq(MerchantStore::getMerchantNo, merchantNo);
        List<MerchantStore> stores = super.list(wrapper);
        return stores.stream().map(this::convertStore).collect(Collectors.toList());
    }

    private MerchantStoreVo convertStore(MerchantStore entity) {
        MerchantStoreVo vo = new MerchantStoreVo();
        BeanUtils.copyProperties(entity, vo);
        if (StrUtil.isNotBlank(vo.getArea())) {
            RegionPathVo region = merchantRegionService.findById(vo.getArea());
            if (region != null) {
                vo.setProvinceName(region.getProvinceName());
                vo.setCityName(region.getCityName());
                vo.setAreaName(region.getAreaName());
            }
        }
        ClerkAccount account = clerkAccountService.getById(entity.getAccountId());
        if (account != null) {
            vo.setAccountName(account.getName());
            vo.setAccountPhone(account.getPhone());
        }
        ClerkAccountRoleMap accountRoleMap = clerkAccountRoleMapService.findByAccountId(entity.getAccountId());
        if (accountRoleMap != null) {
            vo.setRoleId(accountRoleMap.getRoleId());
            ClerkRole role = clerkRoleService.getById(accountRoleMap.getRoleId());
            if (role != null) {
                vo.setRoleName(role.getName());
            }
        }
        return vo;
    }
}
